feat: add client side tools to bridge and new cas events#1609
feat: add client side tools to bridge and new cas events#1609
Conversation
There was a problem hiding this comment.
Pull request overview
Adds support for “client-side tools” in agent resource modeling and extends the chat event protocol/bridge to handle additional tool-call lifecycle events (including an executingToolCall signal and new CAS event handling paths).
Changes:
- Add
ClientSideas a newAgentToolTypeand introduceAgentClientSideToolResourceConfig, including normalization support. - Extend core chat tool-call event models with
executingToolCalland additional start-event fields (isClientSideTool,outputSchema). - Update the CLI Socket.IO chat bridge to parse
endToolCallas a resume signal and add an emitter forexecutingToolCall.
Reviewed changes
Copilot reviewed 4 out of 4 changed files in this pull request and generated 4 comments.
| File | Description |
|---|---|
| packages/uipath/src/uipath/agent/models/agent.py | Adds a new agent tool type + resource config union member and normalizes incoming tool type strings for client-side tools. |
| packages/uipath/src/uipath/_cli/_chat/_bridge.py | Adds support for new CAS tool-call event shapes and introduces an executingToolCall emitter based on resume triggers. |
| packages/uipath-core/src/uipath/core/chat/tool.py | Extends the chat protocol models with executingToolCall and new start-event fields to represent client-side tools. |
| packages/uipath-core/src/uipath/core/chat/init.py | Exports the newly added UiPathConversationExecutingToolCallEvent. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| tool_call_id = request.get("tool_call_id") | ||
| tool_name = request.get("tool_name") | ||
| tool_input = request.get("input") | ||
|
|
||
| if not tool_call_id or not tool_name: | ||
| logger.info( | ||
| f"emit_executing_tool_call_event: missing tool_call_id or tool_name, skipping. tool_call_id={tool_call_id}, tool_name={tool_name}" | ||
| ) | ||
| return | ||
|
|
||
| executing_event = UiPathConversationMessageEvent( | ||
| message_id=self._current_message_id, | ||
| tool_call=UiPathConversationToolCallEvent( | ||
| tool_call_id=tool_call_id, | ||
| executing=UiPathConversationExecutingToolCallEvent( | ||
| tool_name=tool_name, | ||
| input=tool_input, | ||
| ), |
| async def emit_executing_tool_call_event( | ||
| self, resume_trigger: UiPathResumeTrigger | ||
| ) -> None: | ||
| """Emit an executingToolCall event for client-side tool execution. | ||
|
|
||
| Only emits for triggers marked with is_execution_phase=True. | ||
| This fires exactly once per client-side tool call — for Path 3 (no confirm) | ||
| and for Path 4 (after confirmation, on the execution interrupt). | ||
| Confirmation-only interrupts (Paths 2/4 first interrupt) are skipped. | ||
| """ |
| self._tool_confirmation_event = asyncio.Event() | ||
| self._tool_confirmation_value: ( | ||
| UiPathConversationToolCallConfirmationEvent | None | ||
| UiPathConversationToolCallConfirmationEvent | ||
| | UiPathConversationToolCallEndEvent | ||
| | None | ||
| ) = None |
| class AgentClientSideToolResourceConfig(BaseAgentToolResourceConfig): | ||
| """Resource config for client-side tools executed by the client SDK.""" | ||
|
|
||
| type: Literal[AgentToolType.CLIENT_SIDE] = AgentToolType.CLIENT_SIDE | ||
| properties: BaseResourceProperties = Field(default_factory=BaseResourceProperties) | ||
| output_schema: Optional[Dict[str, Any]] = Field(None, alias="outputSchema") | ||
| arguments: Optional[Dict[str, Any]] = Field(default_factory=dict) | ||
|
|
|
|
||
| Only emits for triggers marked with is_execution_phase=True. | ||
| This fires exactly once per client-side tool call — for Path 3 (no confirm) | ||
| and for Path 4 (after confirmation, on the execution interrupt). |
There was a problem hiding this comment.
Maybe explain the paths or just reference the confluence doc https://uipath.atlassian.net/wiki/spaces/JAR/pages/90578682323/Client+side+tools+tool+confirmation+Sequence+Diagrams
| class AgentClientSideToolResourceConfig(BaseAgentToolResourceConfig): | ||
| """Resource config for client-side tools executed by the client SDK.""" | ||
|
|
||
| type: Literal[AgentToolType.CLIENT_SIDE] = AgentToolType.CLIENT_SIDE |
There was a problem hiding this comment.
Can we add an example maybe in agentinterfaces what an example client side tool would look like?
No description provided.